package utils

import (
	log "github.com/sirupsen/logrus"
	"google.golang.org/grpc/codes"
	"google.golang.org/grpc/status"
	"grpc/interceptor"
	"runtime"
)

var (
	customFunc interceptor.RecoveryHandlerFunc
)

const (
	defaultStackSize = 4096
)

func Go(f func()) {
	go func() {
		defer func() {
			if err := recover(); err != nil {
				log.Errorf("[panic] err: %v stack: %s ", err, ErrorUtil().GetCurrentGoroutineStack())
			}
		}()
		f()
	}()
}

// 扩展 异常处理类
type ErrorUtils struct {
}

func ErrorUtil() *ErrorUtils {
	return &ErrorUtils{}
}

// getCurrentGoroutineStack 获取当前Goroutine的调用栈，便于排查panic异常
func (*ErrorUtils) GetCurrentGoroutineStack() string {
	var buf [defaultStackSize]byte
	n := runtime.Stack(buf[:], false)
	return string(buf[:n])
}

func (a *ErrorUtils) InitCurrentException() []interceptor.Option {
	customFunc = func(p interface{}) (err error) {
		log.Errorf("[panic] err: %v stack: %s", p, a.GetCurrentGoroutineStack())
		return status.Errorf(codes.Internal, "服务器内部错误")
	}
	// Shared options for the logger, with a custom gRPC code to log level function.
	opts := []interceptor.Option{
		interceptor.WithRecoveryHandler(customFunc),
	}
	return opts
}
